
import React from 'react';

export default (setData, getData) => (options = {}) => {

    return (CustomComponent) => {
        return class extends React.Component {
            constructor(props) {
                super(props);
                this.state = {};
                // 存储action实例，最终会挂在每个action上
                this.action = {};
                this.models = {};
                this.instanceId = `${Date.now()}Component`;
        
                // model实例
                let modelInstance = getData('modelInstance');
                let actionInstance = getData('actionInstance');

                // 如果配置了actions
                if(Array.isArray(options.actions)) {
                    options.actions.forEach((actionName) => {
                        let action = actionInstance[actionName];

                        if (!action['$instance']) {
                            action['$instance'] = {};
                        }
                        action['$instance'][this.instanceId] = this;
                        
                        this.action[actionName] = action;
                    });
                } 

                // 配置了models
                if(Array.isArray(options.models)) {
                    options.models.forEach((modelName) => {
                        
                        if (Array.isArray(modelName) && modelName.length > 1) {
                            let keyList = [...modelName];
                            let name = keyList.shift();
                            let key = keyList.join('.');
                            let model = modelInstance[name];
                            let handleFuncName = `handleChange${keyList.join('_')}`;

                            this[handleFuncName] = (obj) => {
                                this.setState({
                                    [name]: model.data
                                });
                            }

                            this.state[name] = model.data;
                            this.models[name] = model;

                            model.on(`change:${key}`, this[handleFuncName]);
                        } else {
                            if (Array.isArray(modelName)) {
                                modelName = modelName[0];
                            }
                            let model = modelInstance[modelName];
                            let handleFuncName = `handleChange${modelName}`;

                            this[handleFuncName] = (obj) => {
                                this.setState({
                                    [modelName]: model.data
                                });
                            }
    
                            this.state[modelName] = model.data;
                            this.models[modelName] = model;

                            model.on('change', this[handleFuncName]);
                        }
                    });
                }
            }

            componentWillUnmount() {
                let modelInstance = getData('modelInstance');
                options.models.forEach((modelName) => {
                    if (Array.isArray(modelName)) {
                        let keyList = [...modelName];
                        let name = keyList.shift();
                        let key = keyList.join('.');
                        let model = modelInstance[name];
                        let handleFuncName = `handleChange${keyList.join('_')}`;

                        model.off(`change:${key}`, this[handleFuncName]);
                    } else {
                        if (Array.isArray(modelName)) {
                            modelName = modelName[0];
                        }
                        let handleFuncName = `handleChange${modelName}`;
                        let model = modelInstance[modelName];
                        model.off('change', this[handleFuncName]);
                    }
                });
            }

            render() {
                return (
                    <CustomComponent 
                        {...this.props}
                        {...this.state}
                        action={this.action}
                        instanceName={this.instanceName}
                    />
                )
            }
        }

    }
}